package ua.com.infinite.mobile.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;
import ua.com.infinite.mobile.db.DBAdapter;
import android.content.Context;
import android.os.AsyncTask;

public abstract class DataLoaderBase extends AsyncTask<RequestObject, Void, Boolean> {
	private OnDownloadingListener onDownloadingListener;
	protected DBAdapter db;
	protected Context context;
	private boolean returnDataToCaller;
	protected static HttpClient httpClient;

	public DataLoaderBase(Context context, OnDownloadingListener onDownloadingListener, boolean returnDataToCaller) {
		super();
		this.context = context;
		this.db = new DBAdapter(context);
		this.onDownloadingListener = onDownloadingListener;
		this.returnDataToCaller = returnDataToCaller;
	}

	public OnDownloadingListener getOnCompleteDownloadingListener() {
		return onDownloadingListener;
	}

	public void setOnCompleteDownloadingListener(OnDownloadingListener onDownloadingListener) {
		this.onDownloadingListener = onDownloadingListener;
	}

	public static synchronized HttpClient getHttpClient() {
		if (httpClient != null) {
			return httpClient;
		}
		HttpParams params = new BasicHttpParams();
		HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_0);
		HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);
		HttpProtocolParams.setUseExpectContinue(params, true);

		ConnManagerParams.setTimeout(params, 1000);

		HttpConnectionParams.setConnectionTimeout(params, 5000);
		HttpConnectionParams.setSoTimeout(params, 0);

		SchemeRegistry schReg = new SchemeRegistry();
		schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
		schReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
		ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params, schReg);

		httpClient = new DefaultHttpClient(conMgr, params);
		return httpClient;

	}

	@Override
	protected void onPreExecute() {
		super.onPreExecute();
		onDownloadingListener.onStartDownloading();
	}

	@Override
	protected Boolean doInBackground(RequestObject... params) {

		boolean responseResult = false;
		for (RequestObject requestObject : params) {
			String data = null;
			InputStream inputStream = null;
			int retry = 3;
			int count = 0;
			HttpResponse response = null;
			String result = null;
			while (count < retry) {
				count++;
				try {
					HttpPost httppost = new HttpPost(URLs.getUrl(requestObject.getAction()));
					httppost.setEntity(new UrlEncodedFormEntity(requestObject.getData()));
					response = (HttpResponse) getHttpClient().execute(httppost);
					HttpEntity entity = response.getEntity();
					if (entity != null) {
						inputStream = entity.getContent();
						data = convertStreamToString(inputStream);
						if (data!= null && !data.equals("")) {
							ResponseObject responseObject = new ResponseObject(requestObject.getAction(), data);
							responseResult = manageResponse(responseObject);
							if (returnDataToCaller) {
								onDownloadingListener.returnData(responseObject.getData());
							}
							break;
						}
					} else {
						continue;
					}
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
					continue;
				} catch (ClientProtocolException e) {
					e.printStackTrace();
					continue;
				} catch (IOException e) {
					e.printStackTrace();
					continue;
				}
			}
		}
		return responseResult;
	}

	public abstract boolean manageResponse(ResponseObject responseObject);

	@Override
	protected void onPostExecute(Boolean result) {
		super.onPostExecute(result);
		onDownloadingListener.succesDownloading(result);
		this.cancel(true);
	}

	public static String convertStreamToString(InputStream is) {
		BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		StringBuilder sb = new StringBuilder();
		String line = null;
		try {
			while ((line = reader.readLine()) != null) {
				sb.append(line);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return (sb.toString()).trim();
	}

}
